{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# IPv4 addresses and networks in python 3\n",
    "\n",
    "This notebook provieds a brief overview of the ipaddress module, that was introduced starting with python version 3.3.\n",
    "\n",
    "Further details about this module can be found at the [official python documentation](https://docs.python.org/3.4/library/ipaddress.html).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import ipaddress\n",
    "from ipaddress import IPv4Address, IPv4Network, IPv4Interface"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## creating IPv4 objects using the factory methods\n",
    "\n",
    "The ipaddress module defines some factory functions, that can be used to create new instances for IPv4/IPv6 strings or integers.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Address('10.10.10.128')"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ipaddress.ip_address(\"10.10.10.128\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Network('10.10.10.0/24')"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ipaddress.ip_network(\"10.10.10.0/24\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Network('10.10.10.0/24')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ipaddress.ip_network(\"10.10.10.0/255.255.255.0\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you try to create an IPv4Network instance from a string a `ValueError` is thrown if the host bits are set. If you suspect, that a string will contain such a value, you can disable the `strict option`. Without the `strict` option, the factory function will ignore any host bit that is set."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Network('10.10.10.0/24')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ipaddress.ip_network(\"10.10.10.5/24\", strict=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another way to handle this situation is to use the `IPv4Interface` class. This class has the benefit, that you can extract the `IPv4Address` and the `IPv4Network` objects from a single instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Interface('10.10.10.5/24')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf = ipaddress.ip_interface(\"10.10.10.5/24\")\n",
    "intf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Address('10.10.10.5')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.ip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Network('10.10.10.0/24')"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## gather information from the IPv4Network object\n",
    "\n",
    "Within this notebook, I'll like to continue with the `IPv4Interface` class. This class provides the ability to create the `IPv4Address` or `IPv4Network` object if required, as shown above.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf = ipaddress.ip_interface(\"10.10.10.5/24\")\n",
    "intf.version"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "get different representation of the IPv4 interface, address or network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'10.10.10.5/255.255.255.0'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.with_netmask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'10.10.10.5/24'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.with_prefixlen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'10.10.10.0/255.255.255.0'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network.with_netmask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'10.10.10.5/0.0.0.255'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.with_hostmask"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "get information about the IPv4 interface, address and network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network.is_private"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network.is_reserved"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network.is_global"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.ip.is_multicast"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Address('10.10.10.255')"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network.broadcast_address"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IPv4Address('10.10.10.0')"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network.network_address"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "256"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intf.network.num_addresses"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[IPv4Address('10.1.1.1'),\n",
       " IPv4Address('10.1.1.2'),\n",
       " IPv4Address('10.1.1.3'),\n",
       " IPv4Address('10.1.1.4'),\n",
       " IPv4Address('10.1.1.5'),\n",
       " IPv4Address('10.1.1.6')]"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(IPv4Network(\"10.1.1.0/29\").hosts())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Check if an IPv4 address is part of a network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ipaddr = IPv4Address(\"192.168.1.23\")\n",
    "\n",
    "ipaddr in IPv4Network(\"192.168.1.0/24\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ipaddr in IPv4Network(\"192.168.2.0/24\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Subnetting in python\n",
    "\n",
    "The `ipaddress` module includes various functions to create subnets and supernets, to check whether a network overlaps or not etc.\n",
    "\n",
    "This notebook demonstrates just some basic functions that are required from day to day, further details can be found in the [official python documentation](https://docs.python.org/3.4/library/ipaddress.html).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[IPv4Network('10.1.0.0/20'),\n",
       " IPv4Network('10.1.16.0/20'),\n",
       " IPv4Network('10.1.32.0/20'),\n",
       " IPv4Network('10.1.48.0/20'),\n",
       " IPv4Network('10.1.64.0/20'),\n",
       " IPv4Network('10.1.80.0/20'),\n",
       " IPv4Network('10.1.96.0/20'),\n",
       " IPv4Network('10.1.112.0/20'),\n",
       " IPv4Network('10.1.128.0/20'),\n",
       " IPv4Network('10.1.144.0/20'),\n",
       " IPv4Network('10.1.160.0/20'),\n",
       " IPv4Network('10.1.176.0/20'),\n",
       " IPv4Network('10.1.192.0/20'),\n",
       " IPv4Network('10.1.208.0/20'),\n",
       " IPv4Network('10.1.224.0/20'),\n",
       " IPv4Network('10.1.240.0/20')]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ipnet = IPv4Network(\"10.1.0.0/16\")\n",
    "\n",
    "# prefixlen_diff = number of additional network bits\n",
    "list(ipnet.subnets(prefixlen_diff=4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[IPv4Network('10.1.0.0/20'),\n",
       " IPv4Network('10.1.16.0/20'),\n",
       " IPv4Network('10.1.32.0/20'),\n",
       " IPv4Network('10.1.48.0/20'),\n",
       " IPv4Network('10.1.64.0/20'),\n",
       " IPv4Network('10.1.80.0/20'),\n",
       " IPv4Network('10.1.96.0/20'),\n",
       " IPv4Network('10.1.112.0/20'),\n",
       " IPv4Network('10.1.128.0/20'),\n",
       " IPv4Network('10.1.144.0/20'),\n",
       " IPv4Network('10.1.160.0/20'),\n",
       " IPv4Network('10.1.176.0/20'),\n",
       " IPv4Network('10.1.192.0/20'),\n",
       " IPv4Network('10.1.208.0/20'),\n",
       " IPv4Network('10.1.224.0/20'),\n",
       " IPv4Network('10.1.240.0/20')]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# new_prefix = number of network bits for the new prefix\n",
    "list(ipnet.subnets(new_prefix=20))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.4.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
